import { storageAsync } from './index.js';

/**
 * WebSocket管理类（STOMP协议适配）
 * 负责与后端Spring STOMP WebSocket的连接建立、维护和消息收发
 */
class WebSocketManager {
  constructor() {
    this.ws = null;
    // 使用统一的后端地址配置
    const apiBaseUrl = 'http://10.34.93.196:8080'; // 后端基础地址
    this.url = apiBaseUrl.replace('http', 'ws') + '/websocket'; // 转换为WebSocket URL，使用后端注册的端点
    this.reconnectTimer = null;
    this.reconnectCount = 0;
    this.maxReconnectCount = 5;
    this.reconnectDelay = 3000;
    this.isConnecting = false;
    this.isConnected = false;
    this.messageQueue = [];
    this.listeners = new Map();
    this.token = '';
    this.userId = '';
    this.subscriptions = new Map();
    this.heartbeatInterval = null;
  }

  /**
   * 初始化WebSocket连接（STOMP协议）
   */
  async init() {
    try {
      // 从本地存储获取token和用户信息
      const token = await storageAsync.getItem('token');
      const userInfo = await storageAsync.getItem('userInfo');
      
      if (!token || !userInfo) {
        console.error('WebSocket初始化失败：缺少认证信息');
        return false;
      }

      this.token = token;
      this.userId = userInfo.id;
      return this.connect();
    } catch (error) {
      console.error('WebSocket初始化失败:', error);
      return false;
    }
  }

  /**
   * 建立STOMP WebSocket连接
   */
  connect() {
    if (this.isConnecting || this.isConnected) {
      console.log('WebSocket已在连接中或已连接');
      return false;
    }

    this.isConnecting = true;
    
    try {
      // 创建WebSocket连接
      this.ws = uni.connectSocket({
        url: `${this.url}?userId=${this.userId}`, // 将userId作为查询参数传递，符合后端拦截器要求
        header: {
          'Authorization': `Bearer ${this.token}`,
          'X-User-Id': this.userId // 同时在请求头中传递，增加兼容性
        },
        success: () => {
          console.log('WebSocket连接请求已发送');
        },
        fail: (err) => {
          console.error('WebSocket连接请求发送失败:', err);
          this.isConnecting = false;
          this.handleReconnect();
        }
      });

      // 监听连接打开
      this.ws.onOpen(() => {
        console.log('WebSocket连接已打开');
        this.isConnecting = false;
        this.isConnected = true;
        this.reconnectCount = 0;
        
        // 模拟STOMP握手后的订阅操作
        this.subscribeToUserTopic();
        
        // 发送队列中的消息
        this.flushMessageQueue();
        
        // 触发连接成功事件
        this.emit('connected');
      });

      // 监听连接错误
      this.ws.onError((err) => {
        console.error('WebSocket连接错误:', err);
        this.isConnecting = false;
        this.isConnected = false;
        this.emit('error', err);
        this.handleReconnect();
      });

      // 监听连接关闭
      this.ws.onClose((res) => {
        console.log('WebSocket连接已关闭', res);
        this.isConnecting = false;
        this.isConnected = false;
        this.ws = null;
        this.subscriptions.clear();
        
        // 触发连接关闭事件
        this.emit('disconnected', res);
        
        // 尝试重连
        this.handleReconnect();
      });

      // 监听错误
      this.ws.onError((err) => {
        console.error('WebSocket连接错误:', err);
        this.isConnecting = false;
        this.isConnected = false;
        
        // 触发错误事件
        this.emit('error', err);
      });

      // 监听收到的消息
      this.ws.onMessage((res) => {
        try {
          const data = JSON.parse(res.data);
          
          // 为不同类型的消息添加更详细的日志记录
          if (data.event === 'message') {
            // 详细打印message事件类型的所有字段
            console.log('收到WebSocket消息 [event:message]:', JSON.stringify({
              answer: data.answer,
              conversation_id: data.conversation_id,
              query: data.query,
              user: data.user,
              created_at: data.created_at,
              message_id: data.message_id,
              task_id: data.task_id,
              inputs: data.inputs,
              files: data.files
            }, null, 2));
          } else if (data.event === 'workflow_finished') {
            // 详细打印workflow_finished事件类型的所有字段
            console.log('收到WebSocket消息 [event:workflow_finished]:', JSON.stringify({
              answer: data.data?.outputs?.answer || data.answer,
              conversation_id: data.conversation_id,
              message_id: data.message_id,
              task_id: data.task_id,
              status: data.data?.status
            }, null, 2));
          } else {
            // 其他类型的消息
            console.log('收到WebSocket消息:', data);
          }
          
          // 根据消息类型分发到不同的监听器
          if (data.type) {
            this.emit(`message_${data.type}`, data);
          }
          
          // 如果有event字段，也按event类型分发
          if (data.event) {
            this.emit(data.event, data);
          }
          
          // 触发通用消息事件
          this.emit('message', data);
        } catch (error) {
          console.error('解析WebSocket消息失败:', error);
          console.error('原始消息内容:', res.data);
        }
      });

      return true;
    } catch (error) {
      console.error('WebSocket连接建立失败:', error);
      this.isConnecting = false;
      return false;
    }
  }

  /**
   * 处理重连
   */
  handleReconnect() {
    if (this.reconnectCount >= this.maxReconnectCount) {
      console.error('WebSocket重连次数已达上限');
      this.emit('reconnectFailed');
      return;
    }

    this.reconnectCount++;
    console.log(`WebSocket将在${this.reconnectDelay}ms后进行第${this.reconnectCount}次重连`);
    
    this.reconnectTimer = setTimeout(() => {
      this.connect();
    }, this.reconnectDelay);
  }

  /**
   * 发送消息（适配STOMP协议）
   * @param {Object} data - 要发送的消息数据
   */
  send(data) {
    if (!data) {
      console.error('发送消息失败：消息数据为空');
      return false;
    }

    // 确保消息包含必要的字段
    const message = {
      ...data,
      userId: this.userId,
      timestamp: Date.now()
    };

    // 如果未连接，将消息加入队列
    if (!this.isConnected || !this.ws) {
      console.log('WebSocket未连接，消息已加入队列:', JSON.stringify(message));
      this.messageQueue.push(message);
      
      // 尝试重新连接
      if (!this.isConnecting) {
        console.log('WebSocket未连接，尝试重新连接...');
        this.connect();
      }
      
      return true;
    }

    try {
      // 检测是否为聊天消息，如果是则使用STOMP格式发送
      if (data.conversationId || data.query || data.type === 'chat') {
        console.log('发送聊天消息:', data.conversationId);
        return this.sendChatMessage(message);
      }
      
      // 普通消息使用原来的格式发送
      this.ws.send({
        data: JSON.stringify(message),
        success: () => {
          console.log('消息发送成功:', message);
          return true;
        },
        fail: (err) => {
          console.error('消息发送失败:', err);
          // 发送失败时加入队列
          this.messageQueue.push(message);
          // 触发发送失败事件
          this.emit('sendFailed', { message, error: err });
          return false;
        }
      });
    } catch (error) {
      console.error('发送消息异常:', error);
      this.messageQueue.push(message);
      // 触发发送失败事件
      this.emit('sendFailed', { message, error });
      return false;
    }
  }

  /**
   * 订阅用户专用主题（WebSocket）
   * 由于后端使用原生WebSocket而非STOMP，这里简化为记录订阅状态
   */
  subscribeToUserTopic() {
    // 后端WebSocket实现会自动将会话与用户关联
    // 这里仅记录订阅状态
    const userTopic = `user_${this.userId}`;
    this.subscriptions.set(userTopic, true);
    console.log(`已记录用户会话关联: ${userTopic}`);
    
    // 发送心跳消息以保持连接活跃
    this.startHeartbeat();
  }
  
  /**
   * 开始心跳机制
   */
  startHeartbeat() {
    this.heartbeatInterval = setInterval(() => {
      if (this.isConnected) {
        const heartbeatMessage = {
          type: 'HEARTBEAT',
          content: 'ping',
          senderId: this.userId,
          timestamp: Date.now()
        };
        
        this.ws.send({
          data: JSON.stringify(heartbeatMessage),
          fail: (err) => {
            console.error('发送心跳失败:', err);
          }
        });
      }
    }, 30000); // 每30秒发送一次心跳
  }
  
  /**
   * 停止心跳机制
   */
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
  }

  /**
   * 发送聊天消息（适配后端WebSocket接口）
   * @param {Object} data - 聊天消息数据
   */
  sendChatMessage(data) {
    try {
      // 构建符合后端WebSocketMessage格式的消息
      const messageBody = {
        type: 'CHAT',
        content: data.query || '',
        senderId: this.userId,
        targetId: data.targetId || null,
        data: {
          // 保留原始的conversation_id，即使为空也不自动生成，让后端从外部API获取
          conversation_id: data.conversationId || data.conversation_id || '',
          inputs: data.inputs || {},
          files: data.files || [],
          streaming: data.streaming || false
        },
        timestamp: Date.now()
      };
      
      this.ws.send({
        data: JSON.stringify(messageBody),
        success: () => {
          console.log('聊天消息已发送:', messageBody);
          return true;
        },
        fail: (err) => {
          console.error('发送聊天消息失败:', err);
          this.messageQueue.push(data);
          return false;
        }
      });
    } catch (error) {
      console.error('发送聊天消息异常:', error);
      this.messageQueue.push(data);
      return false;
    }
  }

  /**
   * 发送停止请求（适配后端接口）
   * @param {string} taskId - 任务ID
   */
  sendStopRequest(taskId) {
    if (!this.isConnected || !this.ws) {
      console.warn('WebSocket未连接，无法发送停止请求');
      return false;
    }

    try {
      // 构建符合后端WebSocketMessage格式的停止请求消息
      const messageBody = {
        type: 'SYSTEM',
        content: 'STOP_TASK',
        senderId: this.userId,
        targetId: null,
        data: { task_id: taskId },
        timestamp: Date.now()
      };
      
      this.ws.send({
        data: JSON.stringify(messageBody),
        success: () => {
          console.log('停止请求已发送:', taskId);
          return true;
        },
        fail: (err) => {
          console.error('发送停止请求失败:', err);
          return false;
        }
      });
    } catch (error) {
      console.error('发送停止请求异常:', error);
      return false;
    }
  }

  /**
   * 发送队列中的消息
   */
  flushMessageQueue() {
    if (this.messageQueue.length === 0 || !this.isConnected) {
      return;
    }

    console.log(`开始发送队列中的${this.messageQueue.length}条消息`);
    
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      this.send(message);
    }
  }

  /**
   * 关闭WebSocket连接
   */
  close() {
    // 停止重连定时器
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }

    // 停止心跳定时器
    this.stopHeartbeat();

    // 关闭WebSocket连接
    if (this.ws) {
      try {
        this.ws.close();
        console.log('WebSocket已主动关闭');
      } catch (error) {
        console.error('关闭WebSocket连接失败:', error);
      }
    }

    // 重置状态
    this.isConnecting = false;
    this.isConnected = false;
    this.ws = null;
    this.reconnectCount = 0;
    this.subscriptions.clear();
  }

  /**
   * 注册事件监听器
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数
   */
  on(event, callback) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(callback);
  }

  /**
   * 移除事件监听器
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数，如果不提供则移除该事件的所有监听器
   */
  off(event, callback) {
    if (!this.listeners.has(event)) {
      return;
    }

    if (!callback) {
      this.listeners.delete(event);
    } else {
      const callbacks = this.listeners.get(event);
      const index = callbacks.indexOf(callback);
      if (index > -1) {
        callbacks.splice(index, 1);
      }
    }
  }

  /**
   * 触发事件
   * @param {string} event - 事件名称
   * @param {*} data - 事件数据
   */
  emit(event, data) {
    if (!this.listeners.has(event)) {
      return;
    }

    const callbacks = this.listeners.get(event);
    callbacks.forEach(callback => {
      try {
        callback(data);
      } catch (error) {
        console.error(`执行${event}事件监听器时出错:`, error);
      }
    });
  }

  /**
   * 获取连接状态
   */
  getConnectionStatus() {
    return {
      isConnecting: this.isConnecting,
      isConnected: this.isConnected,
      reconnectCount: this.reconnectCount,
      messageQueueLength: this.messageQueue.length,
      subscriptionCount: this.subscriptions.size
    };
  }

  /**
   * 更新认证信息
   * @param {string} token - 新的token
   * @param {string} userId - 用户ID
   */
  updateAuth(token, userId) {
    const needReconnect = this.isConnected || this.isConnecting;
    
    // 保存新的认证信息
    this.token = token;
    this.userId = userId;
    
    // 如果已经连接，则重新连接以应用新的认证信息
    if (needReconnect) {
      this.close();
      this.connect();
    }
  }
}

// 导出单例实例
export default new WebSocketManager();